package com.bite.system.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.lang.UUID;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.bite.common.core.constants.CacheConstants;
import com.bite.common.core.constants.JwtConstants;
import com.bite.common.core.domain.R;
import com.bite.common.core.enums.ResultCode;
import com.bite.common.core.enums.UserIdentity;

import com.bite.common.security.exception.ServiceException;
import com.bite.common.security.service.TokenService;
import com.bite.common.core.utils.JwtUtils;
import com.bite.common.core.domain.LoginUser;
import com.bite.system.domain.SysUser;
import com.bite.system.domain.dto.SysUserSaveDTO;
import com.bite.system.mapper.SysUserMapper;
import com.bite.system.service.ISysUserService;
import com.bite.system.utils.BCryptUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
@RefreshScope
public class SysUserServiceImpl implements ISysUserService {
    @Autowired
    private SysUserMapper sysUserMapper;

    @Value("${jwt.secret}")
    private String secret;

    @Autowired
    private TokenService tokenService;

    @Override
    public R<String> login(String userAccount, String password) {
        //通过账号搜索在数据库中查询
        SysUser sysUser =  sysUserMapper.
                selectOne(new LambdaQueryWrapper<SysUser>().select(SysUser::getUserId,SysUser::getPassword).
                        eq(SysUser::getUserAccount, userAccount));
        R loginResult = new R();
        if(sysUser == null ){
//            loginResult.setCode(ResultCode.FAILED_USER_NOT_EXISTS.getCode());
//            loginResult.setMsg(ResultCode.FAILED_USER_NOT_EXISTS.getMsg());
//            return loginResult;
            return R.fail(ResultCode.FAILED_USER_NOT_EXISTS);
        }
        if(BCryptUtils.matchesPassword(password, sysUser.getPassword())){
//            loginResult.setCode(ResultCode.SUCCESS.getCode());
            Map<String,Object> claims = new HashMap<>();
            String userKey =  UUID.fastUUID().toString();
            claims.put(JwtConstants.LOGIN_USER_ID,sysUser.getUserId());
            claims.put(JwtConstants.LOGIN_USER_KEY,userKey);
            String token = JwtUtils.createToken(claims, secret);

            //redis中存储敏感信息 ->  表明用户字段   identity   1表示普通用户  2表示管理员用户
            //最好用一个对象来放往redis中存的信息


            //存储哪些信息??

            //使用什么样的数据结构  -> string最合适  最高效
            //key保证唯一  统一前缀 logintoken:userId
            //userId是通过雪花算法来生成的   可以 但是我们可以用一种其他的方式
            //假设公司中使用的是自增主键咋整
            //包括管理员和C端用户   这里表不同  是不是表示对应的id可能相同
            //引入hutool工具包

            String key = CacheConstants.LOGIN_TOKEN_KEY + userKey;
            LoginUser loginUser = new LoginUser();
            loginUser.setIdentity(UserIdentity.ADMIN.getValue());



            //过期时间设置多长????   先定一个720min  大概12小时
            //过期时间怎么记录和控制

            //JWT就不设置过期时间   通过redis 中的值来确定没过期


//            return loginResult;
            return R.ok(tokenService.createToken(sysUser.getUserId(),secret,UserIdentity.ADMIN.getValue()));
        }
//        loginResult.setCode(ResultCode.FAILED_LOGIN.getCode());
//        loginResult.setMsg(ResultCode.FAILED_LOGIN.getMsg());
//        return loginResult;
        return R.fail(ResultCode.FAILED_LOGIN);
    }

    @Override
    public int add(SysUserSaveDTO sysUserSaveDTO) {
        //将DTO转为实体
        //判断避免重复添加
        List<SysUser> sysUserList = sysUserMapper.selectList(new LambdaQueryWrapper<SysUser>().eq(SysUser::getUserAccount, sysUserSaveDTO.getUserAccount()));
        if(CollectionUtil.isNotEmpty(sysUserList)){
            //已经存在
            throw new ServiceException(ResultCode.AILED_USER_EXISTS);
        }
        SysUser sysUser = new SysUser();
        sysUser.setUserAccount(sysUserSaveDTO.getUserAccount());
        //设置加密的密文
        sysUser.setPassword(BCryptUtils.encryptPassword(sysUserSaveDTO.getPassword()));
        int res = sysUserMapper.insert(sysUser);
        return  res;
    }
}
